# simple snake
# 2020-08-13 zbb
import pygame
import sys
import random

bg_color = (255, 255, 255)
snake_head_color = (0, 128, 128)
snake_body_color = (200, 200, 200)
food_color = pygame.Color("yellow")
ROW = 30
COL = 40

pygame.init()
screen_size = (screen_width, screen_height) = 800, 600
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption("simple game")

quit_game = False
f_clock = pygame.time.Clock()  # frame clock
row_width = int(screen_height / ROW)
col_width = int(screen_width / COL)


# Point class
class Point:
    def __init__(self, row, col):
        self.row = 0
        self.col = 0
        self.row = row
        self.col = col

    def draw_point(self, cur_screen, color):
        pos = self.col * col_width, self.row * row_width
        pygame.draw.rect(cur_screen, color, (pos + (row_width, col_width)))

    def copy_point(self):
        return Point(row=self.row, col=self.col)


# snake
head = Point(2, 5)
snake_body = []  # snake body is initiated empty
snake_direction = "right"
is_dead = False
hint_dead = ""


def move_snake(cur_head, cur_direction):
    snake_body.insert(0, cur_head)
    snake_body.pop()
    new_head = cur_head.copy_point()
    if cur_direction == "up":
        new_head.row -= 1
    elif cur_direction == "down":
        new_head.row += 1
    elif cur_direction == "left":
        new_head.col -= 1
    elif cur_direction == "right":
        new_head.col += 1
    return new_head


def eat_food(cur_head, cur_direction):
    snake_body.insert(0, cur_head)
    new_head = cur_head.copy_point()
    if cur_direction == "up":
        new_head.row -= 1
    elif cur_direction == "down":
        new_head.row += 1
    elif cur_direction == "left":
        new_head.col -= 1
    elif cur_direction == "right":
        new_head.col += 1
    return new_head


# food
is_ete = False


def gen_food():
    is_generate = False
    new_food = Point(2, 3)
    while not is_generate:
        food_row = random.randint(0, ROW - 1)
        food_col = random.randint(0, COL - 1)
        new_food = Point(food_row, food_col)
        is_generate = True
        # check if food on the snake
        if new_food.row == head.row and new_food.col == head.col:
            is_generate = False
        for body_point_index in snake_body:
            if new_food.row == body_point_index.row and new_food.col == body_point_index.col:
                is_generate = False
    return new_food


# initial body
def initial_body():
    for index in range(3):
        snake_body.insert(index, Point(head.row, head.col - index - 1))


initial_body()
food = gen_food()

while not quit_game:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quit_game = True
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                quit_game = True
            if event.key == pygame.K_LEFT:
                if snake_direction == "right":
                    break
                snake_direction = "left"
            elif event.key == pygame.K_RIGHT:
                if snake_direction == "left":
                    break
                snake_direction = "right"
            elif event.key == pygame.K_UP:
                if snake_direction == "down":
                    break
                snake_direction = "up"
            elif event.key == pygame.K_DOWN:
                if snake_direction == "up":
                    break
                snake_direction = "down"
    if is_dead:
        print(hint_dead)
        quit_game = True
    if quit_game:
        sys.exit()

    screen.fill(bg_color)
    food.draw_point(screen, food_color)
    if is_ete:
        food = gen_food()
        is_ete = False

    # move
    head = move_snake(head, snake_direction)

    head.draw_point(screen, snake_head_color)
    # snake body
    for body_point in snake_body:
        body_point.draw_point(screen, snake_body_color)
    # eat food
    if head.row == food.row and head.col == food.col:
        is_ete = True
        head = eat_food(head, snake_direction)
    # check hit
    if head.row < 0 or head.row >= ROW or head.col < 0 or head.col >= COL:
        is_dead = True
        hint_dead = "Hitted the wall!"
    # hit itself
    for body_point in snake_body:
        if head.row == body_point.row and head.col == body_point.col:
            is_dead = True
            hint_dead = "Hitted itself!"

    pygame.display.update()
    f_clock.tick(10)
